import axios, {
  AxiosInstance,
  AxiosRequestConfig
  // CustomParamsSerializer
} from 'axios'
import { useCommonStoreHook } from '@/store/modules/common'

import { MusicRequestConfig, MusicHttpResponse, RequestMethods } from './type.d'

// 相关配置请参考：www.axios-js.com/zh-cn/docs/#axios-request-config-1
const defaultConfig: AxiosRequestConfig = {
  // baseURL: 'http://cloud-music.pl-fe.cn/',
  // baseURL: 'http://api-music.cenguigui.cn/',
  // baseURL: 'http://localhost:3000',
  baseURL: 'http://118.89.113.58:3000',
  // 请求超时时间
  timeout: 10000,
  headers: {
    Accept: 'application/json, text/plain, */*',
    'Content-Type': 'application/json',
    'X-Requested-With': 'XMLHttpRequest'
  },
  // 数组格式参数序列化（https://github.com/axios/axios/issues/5142）
  paramsSerializer: {
    // serialize: stringify as unknown as CustomParamsSerializer
  }
}

class MusicRequest {
  constructor() {
    this.httpInterceptorsRequest()
    this.httpInterceptorsResponse()
  }

  /** 保存当前Axios实例对象 */
  private static axiosInstance: AxiosInstance = axios.create(defaultConfig)

  /** 初始化配置对象 */
  private static initConfig: MusicRequestConfig = {}

  private httpInterceptorsRequest(): void {
    MusicRequest.axiosInstance.interceptors.request.use(
      async (config: MusicRequestConfig) => {
        // 优先判断post/get等方法是否传入回掉，否则执行初始化设置等回掉
        if (typeof config.beforeRequestCallback === 'function') {
          config.beforeRequestCallback(config)
          return config
        }
        if (MusicRequest.initConfig.beforeRequestCallback) {
          MusicRequest.initConfig.beforeRequestCallback(config)
          return config
        }
        // 接口设置时间戳
        config.params = {
          ...config.params,
          cookie: useCommonStoreHook().cookie ?? '',
          timestamp: Date.now()
        }
        return config
      },
      (error) => {
        return Promise.reject(error)
      }
    )
  }

  private httpInterceptorsResponse(): void {
    const instance = MusicRequest.axiosInstance
    instance.interceptors.response.use(
      (response: MusicHttpResponse) => {
        const $config = response.config
        if (typeof $config.beforeResponseCallback === 'function') {
          $config.beforeResponseCallback(response)
          return response.data
        }
        if (MusicRequest.initConfig.beforeResponseCallback) {
          MusicRequest.initConfig.beforeResponseCallback(response)
          return response.data
        }
        return response.data
      },
      (error) => {
        return Promise.reject(error)
      }
    )
  }

  /** 通用请求工具函数 */
  public request<T>(
    method: RequestMethods,
    url: string,
    param?: AxiosRequestConfig,
    axiosConfig?: MusicRequestConfig
  ): Promise<T> {
    const config = {
      method,
      url,
      ...param,
      ...axiosConfig
    } as MusicRequestConfig
    return new Promise((resolve, reject) => {
      MusicRequest.axiosInstance
        .request(config)
        .then((response: undefined) => {
          resolve(response)
        })
        .catch((err) => {
          reject(err)
        })
    })
  }

  public get<T, P>(
    url: string,
    param?: AxiosRequestConfig<T>,
    config?: MusicRequestConfig
  ): Promise<P> {
    return this.request<P>('get', url, param, config)
  }

  public post<T, P>(
    url: string,
    param?: AxiosRequestConfig<T>,
    config?: MusicRequestConfig
  ): Promise<P> {
    return this.request<P>('post', url, param, config)
  }
}

export default new MusicRequest()
